Validate documented container and interface features - #721
Conversation
Add an asserted TestProgram for the containers-guide surface, gated error programs for static-action and return-type contract breaches, and a runtime test that a Text implementation of requires action get_area: Number must fail. Co-authored-by: logbie <logbie@users.noreply.github.com>
Store required and implementing return types on runtime signatures and stop a container that claims implements when those concrete types differ, matching the documented static contract. Co-authored-by: logbie <logbie@users.noreply.github.com>
Register inheritance, override, interface-extends, marker, and property access examples; rewrite keyword-reference container snippets to create container / create new; and state that event handlers are not a shipped form. Co-authored-by: logbie <logbie@users.noreply.github.com>
|
Warning Review limit reachedNext included review available in 17 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (18)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
| && !matches!(required_return, Type::Unknown | Type::Any) | ||
| && !matches!(actual_return, Type::Unknown | Type::Any) | ||
| && required_return != actual_return |
There was a problem hiding this comment.
🟡 Compatible subtype returns are rejected
When an interface requires an ancestor container, validate_interface_conformance rejects an implementation returning its descendant. The static checker accepts the same contract.
Prompt for agents
Make runtime interface return-type conformance use the same compatibility semantics as TypeChecker::are_types_compatible instead of raw Type equality. In src/interpreter/mod.rs, validate_interface_conformance must recognize a returned container type as compatible with the required container when it is the same type or extends it transitively. Preserve the existing permissive handling for Unknown and Any, and add runtime coverage where an interface requires an Animal return and an implementing method declares Dog, with Dog extending Animal.
Was this helpful? React with 👍 or 👎 to provide feedback.
| if let (Some(required_return), Some(actual_return)) = | ||
| (&signature.return_type, &return_type) |
There was a problem hiding this comment.
🟡 Inferred return mismatches still run
When an unannotated action infers an incompatible return, validate_interface_conformance skips runtime validation. The program continues despite violating its interface contract.
Prompt for agents
Close the runtime gap for unannotated container actions implementing typed interface requirements. The type checker refines these actions to their inferred return type, but ContainerMethodValue currently retains only the AST annotation, so validate_interface_conformance receives None and cannot reject an incompatible inferred return. Carry the effective inferred return type into runtime metadata or perform an equivalent conformance check before execution becomes authoritative. Add a binary-level test where an interface requires Number and an unannotated implementing action returns Text; the program must exit nonzero before subsequent statements execute.
Was this helpful? React with 👍 or 👎 to provide feedback.
| #[test] | ||
| fn container_with_incompatible_return_type_fails_at_runtime() { | ||
| let program = r#" | ||
| create interface Measurable: | ||
| requires action get_area: Number | ||
| end | ||
|
|
||
| create container Card implements Measurable: | ||
| property label: Text | ||
|
|
||
| action get_area: Text | ||
| return label | ||
| end | ||
| end | ||
|
|
||
| display "should not get here" | ||
| "#; | ||
| let output = run_wfl_program(program, "iface_return_type"); | ||
| assert!( | ||
| !output.status.success(), | ||
| "a return-type mismatch against the interface must fail, got stdout: {} stderr: {}", | ||
| String::from_utf8_lossy(&output.stdout), | ||
| String::from_utf8_lossy(&output.stderr) | ||
| ); | ||
| let stderr = String::from_utf8_lossy(&output.stderr); | ||
| assert!( | ||
| stderr.contains("get_area") && stderr.contains("return"), | ||
| "error should name the mismatched action and return types; got: {stderr}" | ||
| ); | ||
| let stdout = String::from_utf8_lossy(&output.stdout); | ||
| assert!( | ||
| !stdout.contains("should not get here"), | ||
| "program must not continue past the unsatisfied contract" | ||
| ); | ||
| } |
There was a problem hiding this comment.
| create interface <identifier> [extends <identifier-list>] | ||
| create interface <identifier> [extends <identifier-list>]: | ||
| [requires action <identifier> [needs <param>: <type>, ...] [: <type>]]* | ||
| end |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d01e8e7993
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if let (Some(required_return), Some(actual_return)) = | ||
| (&signature.return_type, &return_type) |
There was a problem hiding this comment.
Enforce required returns for unannotated actions
When an implementing action omits its own return annotation, ContainerMethodValue.return_type remains None, so this if let skips the contract check even if the body returns an incompatible value. For example, requires action get_area: Number is still accepted at runtime by an unannotated get_area that returns text; the type checker infers and reports the mismatch, but src/main.rs:930-983 treats type errors as nonfatal warnings and continues execution. Preserve the inferred method type for runtime validation or otherwise validate this case before defining the container.
Useful? React with 👍 / 👎.
| (&signature.return_type, &return_type) | ||
| && !matches!(required_return, Type::Unknown | Type::Any) | ||
| && !matches!(actual_return, Type::Unknown | Type::Any) | ||
| && required_return != actual_return |
There was a problem hiding this comment.
Preserve compatible interface return types at runtime
Compare return types using the same compatibility rules as the type checker rather than strict AST equality. A valid covariant contract such as an interface requiring make: Animal implemented by an action declared make: Dog, where Dog extends Animal, passes TypeChecker::are_types_compatible but now fails here when the container definition executes. This causes previously valid WFL programs to stop at runtime despite passing static conformance.
AGENTS.md reference: AGENTS.md:L20-L22
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Pull request overview
This PR validates and aligns WFL’s documented container/interface feature set with actual runtime behavior, closing a gap where interface return-type mismatches were diagnosed by the typechecker but still allowed to execute.
Changes:
- Enforces interface return-type conformance at runtime during container definition (in addition to existing missing-action/arity checks).
- Adds/updates TestPrograms and Rust tests to cover documented container/interface behavior and expected-failure cases.
- Updates docs and docs examples to reflect current
create container/create newsyntax and corrects a previously overstated “event handlers” claim.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/interface_contract_test.rs | Adds a runtime regression test ensuring an interface return-type mismatch fails execution. |
| TestPrograms/error_examples/interface_static_action.wfl | New expected-failure program: static action must not satisfy requires action. |
| TestPrograms/error_examples/interface_return_type.wfl | New expected-failure program: return-type mismatch must fail at definition/runtime. |
| TestPrograms/docs_examples/keyword_reference/declaration_examples.wfl | Updates container snippet to create container / create new and modern member-call syntax. |
| TestPrograms/docs_examples/keyword_reference/containers_examples.wfl | Updates keyword-reference container examples to current syntax and removes CI-SKIP. |
| TestPrograms/docs_examples/containers/property_access_01.wfl | New docs example demonstrating object.property access. |
| TestPrograms/docs_examples/containers/override_01.wfl | New docs example demonstrating action overrides with extends. |
| TestPrograms/docs_examples/containers/marker_interface_01.wfl | New docs example demonstrating a marker interface. |
| TestPrograms/docs_examples/containers/interface_extends_01.wfl | New docs example demonstrating interface inheritance (extends) and accumulated requirements. |
| TestPrograms/docs_examples/containers/inheritance_01.wfl | New docs example demonstrating multi-property inheritance with extends. |
| TestPrograms/docs_examples/_meta/manifest.json | Registers new container docs examples for validation. |
| TestPrograms/containers/documented_features.wfl | New end-to-end asserted program covering the documented container/interface surface area. |
| src/interpreter/value.rs | Stores declared return types on container methods and interface action signatures. |
| src/interpreter/mod.rs | Adds runtime return-type compatibility validation during interface conformance checks. |
| History/dev-diary/2026/2026-08-30-container-feature-validation.md | Dev diary entry documenting validation results, the discovered mismatch, and test evidence. |
| Docs/reference/reserved-keywords.md | Updates keyword examples to current container/interface syntax. |
| Docs/reference/language-specification.md | Updates container signature example and documents interface definition forms/signatures. |
| Docs/01-introduction/key-features.md | Corrects the container feature bullet to avoid claiming unshipped event-handler attachment syntax. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| Some((_, return_type)) => { | ||
| if let (Some(required_return), Some(actual_return)) = | ||
| (&signature.return_type, &return_type) | ||
| && !matches!(required_return, Type::Unknown | Type::Any) | ||
| && !matches!(actual_return, Type::Unknown | Type::Any) | ||
| && required_return != actual_return | ||
| { | ||
| return Err(RuntimeError::new( | ||
| format!( | ||
| "Container '{container_name}' does not satisfy interface '{}': action '{action_name}' returns {actual_return} but the interface requires {required_return}", | ||
| interface.name | ||
| ), | ||
| line, | ||
| column, | ||
| )); | ||
| } | ||
| } |
Summary
Validates that every user-facing container/interface feature in
Docs/04-advanced-features/containers-oop.md(plus the language-specimplementslist and keyword-reference container syntax) actually works. One documented contract was false at runtime: a required return-type mismatch was reported by the type checker but the program still ran. The runtime now rejects that the same way it already rejects a missing action.Keyword examples that still used
define container calledare rewritten tocreate container/create new. The key-features bullet that claimed event handlers is corrected:event/triggerwork; attaching a handler is not a shipped form.Test evidence
implementswith a concrete return-type mismatch used to run; it now stops at the container definition.TestPrograms/containers/documented_features.wflextends, override, multi-level inheritance → same program +docs_examples/containers/inheritance_01.wfl,override_01.wflrequires action, return types, parameters, interfaceextends, marker interfaces, inherited satisfaction, multipleimplements→ same program +containers/interface_contracts.wfl+ new docs exampleserror_examples/interface_*.wfl,tests/interface_contract_test.rsdefaults→documented_features.wfl,tests/static_container_member_test.rswfl TestPrograms/error_examples/interface_return_type.wflexited 0 and printedunreachable: a return-type mismatch must fail. Commit50904adis the test-only ancestor of the fix.0e36382, that program exits 1 withaction 'get_area' returns Text but the interface requires Number.documented_features.wflreports 14/14 passed.cargo test --test interface_contract_test --test typechecker_container_contract_test --test static_container_member_test --test container_parsing_fixes— 73 passedwfl --test TestPrograms/containers/documented_features.wfl; existingcontainers_comprehensive.wflandcontainers/interface_contracts.wfl;python3 scripts/validate_docs_examples.py— 30/30private/public/parentappear in the keyword tables but are not documented as a working surface in the containers guide and were not treated as shipped user features. Event-handler attachment remains unimplemented and is now labeled as such.Documented container feature test results
To show artifacts inline, enable in settings.